/*
 * PassengerQueue.cpp
 *
 *  Created on: 26/04/2012
 *      Author: alex
 */

#include "PassengerQueue.h"
#include <memory>
#include <vector>

PassengerQueue::PassengerQueue(std::string filePath,std::string keyGeneratorPath,int queueId,EndTypeEnum queueType):
		m_EndType(queueType), m_semaphore(keyGeneratorPath,(char)INITIAL_QUEUE_KEY+queueId,1)
{
	AbstractPipe::PipeTypeEnum pipeType;

	if(queueType == PRODUCER_END)
		pipeType = AbstractPipe::WRITE;
	else
		pipeType = AbstractPipe::READ;

	m_Pipe = new NamedPipe(filePath, pipeType);
	m_FirstPassenger = NULL;
}

PassengerQueue::~PassengerQueue()
{
	if(m_FirstPassenger != NULL)
		delete m_FirstPassenger;

	if(m_Pipe != NULL)
		delete m_Pipe;
}


void PassengerQueue::open()
{
	if(!m_Pipe->open())
		throw new std::exception;
}

void PassengerQueue::close()
{
	m_Pipe->close();
}

void PassengerQueue::create()
{
	if(!m_Pipe->create())
		throw new std::exception;
}

void PassengerQueue::destroy()
{
	m_Pipe->cleanup();
	m_semaphore.destroy();
}

ElevatorPassenger *PassengerQueue::popPassenger()
{
	ElevatorPassenger *passenger;

	m_semaphore.dec();

	if(m_FirstPassenger == NULL)
	{
		passenger = peekPassenger();
		delete passenger;
	}

	passenger = m_FirstPassenger;
	m_FirstPassenger = NULL;

	m_semaphore.inc();
	return m_FirstPassenger;
}

ElevatorPassenger *PassengerQueue::peekPassenger()
{
	if( m_FirstPassenger != NULL )
		delete m_FirstPassenger;

	ElevatorPassenger *passenger = new ElevatorPassenger();
	int passengerSize = passenger->byteSize();

	//Pido un buffer de tamanio adecuado
	std::vector<char> buffer(passengerSize);

	//Recibo del canal la cantidad de bytes
	//que ocupa el msj serializado
	if(!m_Pipe->receive(&buffer[0],passengerSize))
		throw new std::exception;

	//Deserializo el msj del buffer
	passenger->deserialize(&buffer[0]);

	m_FirstPassenger = new ElevatorPassenger(*passenger);

	return passenger;
}

void PassengerQueue::pushPassenger(ElevatorPassenger & passenger)
{
	int passengerSize =passenger.byteSize();

	//Pido un buffer de tamanio adecuado
	std::vector<char> buffer(passengerSize);

	//Serializo el pasajero en el buffer
	passenger.serialize(&buffer[0]);

	//Envio el buffer
	if(!m_Pipe->send(&buffer[0],passengerSize))
		throw new std::exception;
}

void PassengerQueue::deletePeekedPassenger()
{
	if(m_FirstPassenger != NULL)
	{
		delete m_FirstPassenger;
		m_FirstPassenger = NULL;
	}
}

bool PassengerQueue::hasPassengers()
{
	return m_Pipe->hasReadableData();
}

